package com.loveprogrammer.eternity.model;

import com.alibaba.fastjson.annotation.JSONField;
import com.loveprogrammer.eternity.action.BaseAction;
import com.loveprogrammer.eternity.common.Tuple;
import com.loveprogrammer.eternity.enums.*;
import com.loveprogrammer.eternity.factory.EffectFactory;
import com.loveprogrammer.eternity.factory.suit.SuitEffect;
import com.loveprogrammer.eternity.factory.template.JobTemplate;
import com.loveprogrammer.eternity.model.attack.AttackEntity;
import com.loveprogrammer.eternity.model.attack.AttackResult;
import com.loveprogrammer.eternity.model.effect.AbstractEffect;
import com.loveprogrammer.eternity.model.effect.Effect;
import com.loveprogrammer.eternity.model.effect.SuckBloodEffect;
import com.loveprogrammer.eternity.model.product.Equipment;
import com.loveprogrammer.eternity.model.product.Goods;
import com.loveprogrammer.eternity.model.product.equipment.Equips;
import com.loveprogrammer.eternity.notify.Notify;
import com.loveprogrammer.eternity.skill.Skill;
import com.loveprogrammer.eternity.skill.State;
import com.loveprogrammer.eternity.skill.support.states.DazeState;

import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public abstract class Character extends BaseAction implements Usual, Attackable, WearEquipment, Serializable {

    protected int id;                         // 角色id
    protected String name;                   // 角色信息模板
    // protected int attack;                    // 攻击力
    protected int strength;                  // 力量 影响物理输出 物理技能输出
    protected int armature;                 // 护甲值 影响物理防御和法术防御
    protected int constitution;               // 体质 影响生命值 一点体质增加10点生命值
    protected int magic;                       // 魔力 影响法术输出 法术技能输出
    protected int technique;                   // 技巧 影响闪避率、暴击率
    protected int speed;                         // 攻击速度

    protected AtomicInteger hp;                            // 生命值 必须是一个线程安全的变量
    protected int hpMax;                            // 最大生命值

    protected int baseStrength;                  // 基础力量
    protected int baseArmature;                 // 基础护甲
    protected int baseConstitution;               // 基础体质
    protected int baseMagic;                       // 基础魔力
    protected int baseTechnique;                   // 基础技巧
    protected int baseSpeed;                         // 基础速度

    protected int baseHp;                            // 基础生命值

    protected int level;                           // 级别
    protected int star = 1;                            // 星级 初始1星 最大可强化到10星
    protected MonsterQualityEnum monsterQualityEnum;  // 作为野怪的级别
    /**
     * 当前经验值
     **/
    protected Integer currentExp;

    /**
     * 下一级所需经验值
     **/
    protected Integer nextLevelNeedExp;

    // 装备的装备
    private Equips equips;

    /**
     * 技能 野怪也有技能 宠物也需要技能 内有冷却时间
     **/
    @JSONField(serialize=false)
    private List<Skill> skills;

    /**
     * 状态 正面状态 负面状态
     **/
    @JSONField(serialize=false)
    private List<State> states;

    private List<AbstractEffect> effects = new ArrayList<>();

    // 物理攻击 0 法术攻击 1
    private int attackType;

    // 毒抗
    private int poisonResistance;

    // 火抗
    private int flameResistance;

    // 电抗
    private int thunderResistance;

    // 冰抗
    private int iceResistance;

    // 暴击率加成
    private int criticalStrikeRateAdd;

    // 更好装备获得加成
    private int betterEquipmentRateAdd;

    // 闪避率加成
    private int dodgeChanceAdd;

    // 命中率 一般只有武器 或者套装才增加命中率
    private int hitRateAdd;

    // 1 前排 2 后排
    private int position;

    public Character() {

    }

    public Character(int id,String name, int level, int strength, int armature,
                     int constitution, int magic, int technique, int speed, int attackType, int poisonResistance,
                     int flameResistance, int thunderResistance, int iceResistance, int position) {
        this.id = id;
        this.name = name;
        this.level = level;
        this.strength = strength;
        this.armature = armature;
        this.constitution = constitution;
        this.hp = new AtomicInteger(this.constitution * 10);
        this.hpMax = this.hp.get();
        this.speed = speed;
        this.magic = magic;
        this.technique = technique;
        this.skills = new ArrayList<>();
        this.equips = new Equips();
        this.states = new ArrayList<>();

        // 基础属性用于计算增幅型的技能
        this.baseStrength = strength;
        this.baseArmature = armature;
        this.baseConstitution = constitution;
        this.baseHp = this.constitution * 10;
        this.baseSpeed = speed;
        this.baseMagic = magic;
        this.baseTechnique = technique;

        this.attackType = attackType;
        this.currentExp = 0;
        this.nextLevelNeedExp = LevelExpEnum.getByLevel(level+1).getExp();

        this.poisonResistance = poisonResistance;
        this.flameResistance = flameResistance;
        this.thunderResistance = thunderResistance;
        this.iceResistance = iceResistance;
        this.position = position;
    }

    public Character(int id,String name, int strength, int armature, int constitution, int magic, int technique, int speed,
                     AtomicInteger hp, int hpMax, int baseStrength, int baseArmature, int baseConstitution, int baseMagic,
                     int baseTechnique, int baseSpeed, int baseHp, int level, MonsterQualityEnum monsterQualityEnum,
                     Integer currentExp, Integer nextLevelNeedExp, Equips equips, List<Skill> skills, List<State> states, int attackType,
                     int poisonResistance, int flameResistance, int thunderResistance, int iceResistance, int position) {
        this.id = id;
        this.name = name;
        this.strength = strength;
        this.armature = armature;
        this.constitution = constitution;
        this.magic = magic;
        this.technique = technique;
        this.speed = speed;
        this.hp = hp;
        this.hpMax = hpMax;
        this.baseStrength = baseStrength;
        this.baseArmature = baseArmature;
        this.baseConstitution = baseConstitution;
        this.baseMagic = baseMagic;
        this.baseTechnique = baseTechnique;
        this.baseSpeed = baseSpeed;
        this.baseHp = baseHp;
        this.level = level;
        this.monsterQualityEnum = monsterQualityEnum;
        this.currentExp = currentExp;
        this.nextLevelNeedExp = nextLevelNeedExp;
        this.equips = equips;
        this.skills = skills;
        this.states = states;
        this.attackType = attackType;


        this.poisonResistance = poisonResistance;
        this.flameResistance = flameResistance;
        this.thunderResistance = thunderResistance;
        this.iceResistance = iceResistance;
        this.position = position;
    }

    public String string = "\t\t\t\t\t\t\t\t\t";

    @Override
    public boolean checkDead() {
        return hp.get() <= 0;
    }

    //角色打印信息的重写
    public String prettyPrint() {
        return string + "*****信息****\n" +
                string + "姓名：" + this.name + "\n" +
                string + "级别" + this.level + "\n" +
                string + "血量：" + this.hp + "\n" +
                string + "力量：" + this.strength + "\n" +
                string + "法力：" + this.magic + "\n" +
                string + "技巧：" + this.technique + "\n" +
                string + "护甲值" + this.armature + "\n" +
                string + "速度" + this.speed + "\n" +
                string + "毒抗" + this.poisonResistance + "\n" +
                string + "火抗" + this.flameResistance + "\n" +
                string + "雷抗" + this.thunderResistance + "\n" +
                string + "冰抗" + this.iceResistance + "\n" +
                string + "技能:" + "\n" + this.printSkills() + "\n" +
                string + "当前经验" + this.currentExp + "\n" +
                string + "下一级经验" + this.nextLevelNeedExp + "\n" +
                string + "" + "*************";
    }

    private String printSkills() {
        StringBuilder builder = new StringBuilder();
        for (Skill skill : getSkills()) {
            builder.append(string).append(skill.print()).append("\n");
        }
        return builder.toString();
    }

    //角色打印信息的重写
    public String toString() {
        return "**** 名称：" + this.name + " " +
                "级" + this.level + " " +
                "血：" + this.hp + " " +
                "甲: " + this.armature + " " +
                "力:" + this.strength + " " +
                "法:" + this.magic + " " +
                "技:" + this.technique + " " +
                "速:" + this.speed + " " +
                "抗性[毒:" + this.poisonResistance + " " +
                "火:" + this.flameResistance + " " +
                "雷:" + this.thunderResistance + " " +
                "冰:" + this.iceResistance + "] " +
                "经验(" + this.currentExp + "/" + this.nextLevelNeedExp + ") ****";
    }

    public String simplePrint() {
        return "**** 名称：" + this.name + " " +
                "级别" + this.level + " " +
                "血量:" + this.hp + " " +
                "护甲值:" + this.armature + " " +
                "力量:" + this.strength + " " +
                "法力:" + this.magic + " " +
                "技巧:" + this.technique + " " +
                "速度:" + this.speed + "****";
    }

    @Override
    public String wear(Equipment equipment, int weaponType) {
        String takeOffEquipmentId = null;
        // 装备级别要小于等于英雄的等级
        if(equipment.getLevel() > 1 && equipment.getLevel() > getLevel()){
            eventManager.notifyMessage("对不起，装备等级高于英雄，无法穿戴", 1);
            return null;
        }
        // 先看同类的是否存在，如果存在，先脱再穿
        EquipmentEnum equipmentPosition = equipment.getEquipmentPosition();
        switch (equipmentPosition.getCode().toLowerCase()) {
            case "weapon":
                if(weaponType != equipment.getWeaponTypeEnum().getCode()){
                    eventManager.notifyMessage("对不起，该武器不适合英雄，无法穿戴", 1);
                    return null;
                }
                if (equips.getWeapon() != null) {
                    takeOffEquipmentId = takeOff(equips.getWeapon());
                }
                equips.setWeapon(equipment);
                break;
            case "breastplate":
                if (equips.getBreastplate() != null) {
                    takeOffEquipmentId = takeOff(equips.getBreastplate());
                }
                equips.setBreastplate(equipment);
                break;
            case "shield":
                if (equips.getShield() != null) {
                    takeOffEquipmentId = takeOff(equips.getShield());
                }
                equips.setShield(equipment);
                break;
            case "shoes":
                if (equips.getShoes() != null) {
                    takeOffEquipmentId = takeOff(equips.getShoes());
                }
                equips.setShoes(equipment);
                break;
            case "helmet":
                if (equips.getHelmet() != null) {
                    takeOffEquipmentId = takeOff(equips.getHelmet());
                }
                equips.setHelmet(equipment);
                break;
            case "gloves":
                if (equips.getGlove() != null) {
                    takeOffEquipmentId = takeOff(equips.getGlove());
                }
                equips.setGlove(equipment);
                break;
            case "necklace":
                if (equips.getNecklace() != null) {
                    takeOffEquipmentId = takeOff(equips.getNecklace());
                }
                equips.setNecklace(equipment);
                break;
            case "leftring":
                if (equips.getLeftRing() != null) {
                    takeOffEquipmentId = takeOff(equips.getLeftRing());
                }
                equips.setLeftRing(equipment);
                break;
            case "rightring":
                if (equips.getRightRing() != null) {
                    takeOffEquipmentId = takeOff(equips.getRightRing());
                }
                equips.setRightRing(equipment);
                break;
            case "legarmor":
                if (equips.getLegArmor() != null) {
                    takeOffEquipmentId = takeOff(equips.getLegArmor());
                }
                equips.setLegArmor(equipment);
                break;
            case "belt":
                if (equips.getBelt() != null) {
                    takeOffEquipmentId =  takeOff(equips.getBelt());
                }
                equips.setBelt(equipment);
                break;
            case "barcer":
                if (equips.getBarcer() != null) {
                    takeOffEquipmentId = takeOff(equips.getBarcer());
                }
                equips.setBarcer(equipment);
                break;
            case "shoulder":
                if (equips.getShoulder() != null) {
                    takeOffEquipmentId = takeOff(equips.getShoulder());
                }
                equips.setShoulder(equipment);
                break;
            default:
                eventManager.notifyMessage("穿戴装备失败" + equipment.getName(), 1);
                return null;
        }
        wearEquipment(equipment);
        return takeOffEquipmentId;
    }

    private void wearEquipment(Equipment equipment) {
        eventManager.notifyMessage("穿戴装备" + equipment.getName() + " 成功", 1);
        // 穿装备就是整体属性提升
        this.setStrength(this.strength + equipment.getStrength());
        this.setArmature(this.armature + equipment.getArmature());
        this.setConstitution(this.constitution + equipment.getConstitution());
        this.hp.addAndGet(equipment.getConstitution() * 10 + equipment.getHp());
        this.hpMax = this.hp.get();
        this.setMagic(this.magic + equipment.getMagic());
        this.setTechnique(this.technique + equipment.getTechnique());
        this.setSpeed(this.speed + equipment.getSpeed());
        // 装备提升的抗性
        this.setThunderResistance(this.thunderResistance + equipment.getThunderResistance());
        this.setFlameResistance(this.flameResistance + equipment.getFlameResistance());
        this.setPoisonResistance(this.poisonResistance + equipment.getPoisonResistance());
        this.setIceResistance(this.iceResistance + equipment.getIceResistance());

        // 如果是套装，要看检查套装的效果
        if(equipment.getSuitId() > 0){
            equips.checkSuitEffect(this, equipment);
        }
        if(equipment.getEffects().size() > 0){
            for (Goods.GoodsEffectTemplate effect : equipment.getEffects()) {
                // 先获取
                AbstractEffect abstractEffect = EffectFactory.getEffectById(effect.getTemplateId());
                abstractEffect.setId(effect.getId());
                regEffect(abstractEffect);
            }
        }
        equips.getAll().add(equipment);
        equipment.setUsed(true);
    }

    @Override
    public boolean acquireState(State state, int time) {
        // 是否有抵消的状态
        if(this.states == null){
            this.states = new ArrayList<>();
        }else{
            // 是否有抵抗状态 中毒状态无效
            Optional<State> first = this.states.stream().filter(e -> e.id() == state.counterId()).findFirst();
            if(first.isPresent()){
                return false;
            }
            // 状态只能有一个存在 这个是假的 状态目前只能叠加
            // this.states.removeIf(e -> e.id() == state.id());
        }
        this.states.add(state);
        return true;
    }

    @Override
    public boolean removeState(State state) {
        // 同一种状态只能有一个存在 不一定
        this.states.remove(state);
        return true;
    }

    @Override
    public String takeOff(Equipment equipment) {
        // 脱装备就是整体属性下降
        this.setStrength(this.strength - equipment.getStrength());
        this.setArmature(this.armature - equipment.getArmature());
        this.setConstitution(this.constitution - equipment.getConstitution());
        this.hp.addAndGet(-equipment.getHp());
        this.setMagic(this.magic - equipment.getMagic());
        this.setTechnique(this.technique - equipment.getTechnique());
        this.setSpeed(this.speed - equipment.getSpeed());
        this.setPoisonResistance(this.poisonResistance - equipment.getPoisonResistance());
        this.setFlameResistance(this.flameResistance - equipment.getFlameResistance());
        this.setThunderResistance(this.thunderResistance - equipment.getThunderResistance());
        this.setIceResistance(this.iceResistance - equipment.getIceResistance());

        if(equipment.getSuitId() > 0){
            equips.checkSuitEffectTakeOff(this,equipment);
        }
        if(equipment.getEffects().size() > 0){
            List<String> list = equipment.getEffects().stream().map(Goods.GoodsEffectTemplate::getId).distinct()
                    .collect(Collectors.toList());
            effects.removeIf(e -> list.contains(e.getId()));
        }
        equipment.setUsed(false);
        equips.getAll().remove(equipment);
        return equipment.getId();
    }

    // 发动技能是公共的
    @Override
    public Tuple<String, List<Character>> tryToLaunchSkill(List<Skill> skillList,
                                                           List<? extends Character> campA,
                                                           List<? extends Character> campB,
                                                           ScheduledExecutorService subFightExecutorService) {
        skillList.sort(Comparator.comparing(Skill::order));
        for (Skill skill : skillList) {
            // 如果是主动技能
            if (skill.opportunityPassive() == PassiveOpportunityTypeEnum.ACTIVE.getCode()) {
                Tuple<String, List<Character>> launch = skill.launch(this,campA, campB, subFightExecutorService);
                if (launch == null) {
                    continue;
                }
                return launch;
            }
        }
        return null;
    }

    @Override
    public void release(List<? extends Character> campA, List<? extends Character> campB) {
        // 死亡后的一些操作
        List<Skill> passiveSkills = getSkills().stream().filter(e -> e.opportunityPassive() != 0).collect(Collectors.toList());
        if (!passiveSkills.isEmpty()) {
            for (Skill passiveSkill : passiveSkills) {
                passiveSkill.release(this,campA, campB);
            }
        }
    }

    // 排版的方法:让内容都显示在屏幕的中间
    public static void typeset() {                 //排版的方法:让内容都显示在屏幕的中间
        System.out.print("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t");
    }

    public abstract int getDeadExp();

    protected abstract AttackEntity getHarm();

    public void setName(String name) {
        this.name = name;
    }

    public void setStrength(int strength) {
        this.strength = strength;
    }

    public void setConstitution(int constitution) {
        this.constitution = constitution;
    }

    public void setMagic(int magic) {
        this.magic = magic;
    }

    public void setTechnique(int technique) {
        this.technique = technique;
    }

    public void setArmature(int armature) {
        this.armature = armature;
    }

    public int getArmature() {
        return armature;
    }

//    public void setHp(int hp) {
//        this.hp = new AtomicInteger(hp);
//    }


    public String getName() {
        return name;
    }

    public int getStrength() {
        return strength;
    }

    public int getConstitution() {
        return constitution;
    }

    public int getMagic() {
        return magic;
    }

    public int getTechnique() {
        return technique;
    }

    public AtomicInteger hp() {
        return hp;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public Integer getCurrentExp() {
        return currentExp;
    }

    public void setCurrentExp(Integer currentExp) {
        this.currentExp = currentExp;
    }

    public Integer getNextLevelNeedExp() {
        return nextLevelNeedExp;
    }

    public int setNextLevelNeedExp() {
        // 需要的经验值越来越高
        this.nextLevelNeedExp = LevelExpEnum.getByLevel(level).getExp();
        return this.nextLevelNeedExp;
    }

    public MonsterQualityEnum getMonsterQualityEnum() {
        return monsterQualityEnum;
    }

    public void setMonsterQualityEnum(MonsterQualityEnum monsterQualityEnum) {
        this.monsterQualityEnum = monsterQualityEnum;
    }

    public abstract void levelUp(int exp);

    public Equips getEquips() {
        if(equips == null){
            equips = new Equips();
        }
        return equips;
    }

    public void setEquips(Equips equips) {
        this.equips = equips;
    }

    public List<Skill> getSkills() {
        if(skills == null)
            skills = new ArrayList<>();
        return skills;
    }

    public void setSkills(List<Skill> skills) {
        this.skills = skills;
    }

    public int getBaseStrength() {
        return baseStrength;
    }

    public int getBaseArmature() {
        return baseArmature;
    }

    public int getBaseConstitution() {
        return baseConstitution;
    }

    public int getBaseMagic() {
        return baseMagic;
    }

    public int getBaseTechnique() {
        return baseTechnique;
    }

    public int getBaseSpeed() {
        return baseSpeed;
    }

    public int getBaseHp() {
        return baseHp;
    }

    public void setBaseStrength(int baseStrength) {
        this.baseStrength = baseStrength;
    }

    public void setBaseArmature(int baseArmature) {
        this.baseArmature = baseArmature;
    }

    public void setBaseConstitution(int baseConstitution) {
        this.baseConstitution = baseConstitution;
    }

    public void setBaseMagic(int baseMagic) {
        this.baseMagic = baseMagic;
    }

    public void setBaseTechnique(int baseTechnique) {
        this.baseTechnique = baseTechnique;
    }

    public void setBaseSpeed(int baseSpeed) {
        this.baseSpeed = baseSpeed;
    }

    public void setBaseHp(int baseHp) {
        this.baseHp = baseHp;
    }

    public int getHpMax() {
        return hpMax;
    }

    @Override
    public void acquireSkill(Skill skill) {
        if(skills == null){
            skills = new ArrayList<>();
        }
        // 尝试移除，再加入
        this.skills.removeIf(e -> e.getId() == skill.getId());
        this.skills.add(skill);
    }

    public int getCurrentHp() {
        return hp.get();
    }

    public int getAttackType() {
        return attackType;
    }

    public void setAttackType(int attackType) {
        this.attackType = attackType;
    }

    public AtomicInteger getHp() {
        return hp;
    }

    public void setHp(AtomicInteger hp) {
        this.hp = hp;
    }

    public void setHpMax(int hpMax) {
        this.hpMax = hpMax;
    }

    public void setNextLevelNeedExp(Integer nextLevelNeedExp) {
        this.nextLevelNeedExp = nextLevelNeedExp;
    }

    public List<State> getStates() {
        return states;
    }

    public void setStates(List<State> states) {
        this.states = states;
    }

    public abstract void reset();

    public void resetSuitEffect(SuitEffect effectOld, SuitEffect effectNew) {
        if(effectOld == null){
            effectOld = new SuitEffect();
        }
        if(effectOld.getCount() == effectNew.getCount()){
            return;
        }
        this.setTechnique(technique - effectOld.getTechnique() + effectNew.getTechnique());
        this.setMagic(magic - effectOld.getMagic() + effectNew.getMagic());
        this.setStrength(strength - effectOld.getStrength() + effectNew.getStrength());
        this.setArmature(armature - effectOld.getArmature() + effectNew.getArmature());
        this.setSpeed(speed - effectOld.getSpeed() + effectNew.getSpeed());
        this.setConstitution(constitution - effectOld.getConstitution() + effectNew.getConstitution());
    }

    public int getStar() {
        return star;
    }

    public void setStar(int star) {
        this.star = star;
    }

    public int getPoisonResistance() {
        return poisonResistance;
    }

    public void setPoisonResistance(int poisonResistance) {
        this.poisonResistance = poisonResistance;
    }

    public int getFlameResistance() {
        return flameResistance;
    }

    public void setFlameResistance(int flameResistance) {
        this.flameResistance = flameResistance;
    }

    public int getThunderResistance() {
        return thunderResistance;
    }

    public void setThunderResistance(int thunderResistance) {
        this.thunderResistance = thunderResistance;
    }

    public void tryToWearAndSale(List<Goods> fallingGoods) {

        for (Goods fallingGood : fallingGoods) {
            tryToWearAndSale(fallingGood);
        }

    }

    public void tryToWearAndSale(Goods fallingGood) {
        if(fallingGood instanceof Equipment){
            Equipment equipment = (Equipment) fallingGood;
            EquipmentEnum equipmentPosition = equipment.getEquipmentPosition();
            boolean wear = false;
            switch (equipmentPosition.getCode().toLowerCase()) {
                case "weapon":
                    if (equips.getWeapon() == null) {
                        equips.setWeapon(equipment);
                        wear = true;
                    }
                    break;
                case "breastplate":
                    if (equips.getBreastplate() == null) {
                        equips.setBreastplate(equipment);
                        wear = true;
                    }
                    break;
                case "shield":
                    if (equips.getShield() == null) {
                        equips.setShield(equipment);
                        wear = true;
                    }
                    break;
                case "shoes":
                    if (equips.getShoes() == null) {
                        equips.setShoes(equipment);
                        wear = true;
                    }
                    break;
                case "helmet":
                    if (equips.getHelmet() == null) {
                        equips.setHelmet(equipment);
                        wear = true;
                    }
                    break;
                case "gloves":
                    if (equips.getGlove() == null) {
                        equips.setGlove(equipment);
                        wear = true;
                    }
                    break;
                case "necklace":
                    if (equips.getNecklace() == null) {
                        equips.setNecklace(equipment);
                        wear = true;
                    }
                    break;
                case "leftring":
                    if (equips.getLeftRing() == null) {
                        equips.setLeftRing(equipment);
                        wear = true;
                    }
                    break;
                case "rightring":
                    if (equips.getRightRing() == null) {
                        equips.setRightRing(equipment);
                        wear = true;
                    }
                    break;
                case "legarmor":
                    if (equips.getLegArmor() == null) {
                        equips.setLegArmor(equipment);
                        wear = true;
                    }
                    break;
                case "belt":
                    if (equips.getBelt() == null) {
                        equips.setBelt(equipment);
                        wear = true;
                    }
                    break;
                case "barcer":
                    if (equips.getBarcer() == null) {
                        equips.setBarcer(equipment);
                        wear = true;
                    }
                    break;
                case "shoulder":
                    if (equips.getShoulder() == null) {
                        equips.setShoulder(equipment);
                        wear = true;
                    }
                    break;
                default:
                    break;
            }
            if(wear){
                wearEquipment(equipment);
            }
        }
    }

    public int getIceResistance() {
        return iceResistance;
    }

    public void setIceResistance(int iceResistance) {
        this.iceResistance = iceResistance;
    }


    @Override
    public AttackResult defence(AttackEntity harm) {
        // 有些技能无法闪避 是状态伤害，无法闪避
        if(harm.getState() == null && ( harm.getSkill() == null || harm.getSkill().canBeDodged() )) {
            // 先看闪避率 和暴击率一样 速度也会提升闪避率
            int percents = (this.getTechnique() + this.getSpeed()) * 100 / (Math.abs(this.getTechnique())
                    +  Math.abs(this.getSpeed()) + 40000);
            percents = Math.min(percents,50);
            // 要加上自身的闪避率加成 减去攻击方的准确率加成
            percents = percents + getDodgeChanceAdd() - harm.getHitRateAdd() ;
            // 闪避率最高不能超过65%
            if (new Random().nextInt(100) < Math.min(percents,65)) {
                return new AttackResult(" 被躲过了", 0);
            }
        }
        double rate;
        switch (harm.getAttackType()) {
            case NORMAL:
                rate  = 1 - (this.armature * 1.5) / (Math.abs(this.armature) + 2002);
                break;
            case MAGIC:
                // 法抗与法力值相当 暂时还是用护甲值
                rate  = 1 - (this.armature * 1.5) / (Math.abs(this.armature) + 2002);
                break;
            case POISON:
                // 毒素的抗性
                rate  = 1 - Math.min(this.getPoisonResistance() * 1.0 / 100,100);
                break;
            case FLAME:
                // 火系的抗性
                rate  = 1 - Math.min(this.getFlameResistance() * 1.0 / 100,100);
                break;
            case THUNDER:
                // 雷系的抗性
                rate  = 1 - Math.min(this.getThunderResistance() * 1.0 / 100,100);
                break;
            case ICE:
                // 毒素的抗性
                rate  = 1 - Math.min(this.getIceResistance() * 1.0 / 100,100);
                break;
            default:
                rate = 1.0;
                break;
        }
        // 每一点护甲直接抵消 0.2点伤害 但最多只能抵消75的伤害%
        double v = this.armature * 0.65;
        // TODO 检查负面状态 例如伤害加深
        return new AttackResult((int)(Math.max(harm.getHarm() * rate - v,harm.getHarm() * rate * 0.25)));
    }

    public State checkDazeState() {
        if(states != null && states.size() > 0){
            Optional<State> dazeState = states.stream().filter(e -> e instanceof DazeState).findFirst();
            if(dazeState.isPresent())
                return dazeState.get();
        }
        return null;
    }

    @Override
    public void regEffect(AbstractEffect effect) {
        if(effects == null){
            effects = new ArrayList<>();
        }
        this.effects.add(effect);
    }

    @Override
    public void delEffect(AbstractEffect effect) {
        this.effects.remove(effect);
    }

//    @Override
//    public StringBuilder notifyEffect(Character attack, EffectTimeEnum effectTimeEnum,
//                                      AttackResult entity,
//                                      List<? extends Character> attackList, Character... defence) {
//        StringBuilder result = new StringBuilder();
//        if(effects == null){
//            return result;
//        }
//        // TODO 这里应该先分类聚合
//        for (Effect effect : effects) {
//            result.append(effect.update(attack,effectTimeEnum,entity,attackList,defence));
//        }
//        return result;
//    }

    public List<AbstractEffect> getEffects() {
        return effects;
    }

    public void setEffects(List<AbstractEffect> effects) {
        this.effects = effects;
    }

    public int getCriticalStrikeRateAdd() {
        return criticalStrikeRateAdd;
    }

    public void setCriticalStrikeRateAdd(int criticalStrikeRateAdd) {
        this.criticalStrikeRateAdd = criticalStrikeRateAdd;
    }

    public int getBetterEquipmentRateAdd() {
        return betterEquipmentRateAdd;
    }

    public void setBetterEquipmentRateAdd(int betterEquipmentRateAdd) {
        this.betterEquipmentRateAdd = betterEquipmentRateAdd;
    }

    public int getDodgeChanceAdd() {
        return dodgeChanceAdd;
    }

    public void setDodgeChanceAdd(int dodgeChanceAdd) {
        this.dodgeChanceAdd = dodgeChanceAdd;
    }

    public int getHitRateAdd() {
        return hitRateAdd;
    }

    public void setHitRateAdd(int hitRateAdd) {
        this.hitRateAdd = hitRateAdd;
    }

    public int getId() {
        return id;
    }

    // 转职
    public void transfer(JobTemplate jobTemplate) throws IOException, ClassNotFoundException {
        // 首先要替换到自己的模板



    }

    public int getPosition() {
        return position;
    }

    public void setPosition(int position) {
        this.position = position;
    }
}
